package cn.yaoud.salus.imexport.component;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.validation.ConstraintViolation;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;

import cn.yaoud.salus.async.task.listener.ImportListenerCallback;
import cn.yaoud.salus.async.task.model.vo.ErrorMessage;
import cn.yaoud.salus.common.excel.kit.Validators;
import cn.yaoud.salus.imexport.processor.ImportProcessor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author wny
 * @date 2025/3/5 14:10
 * @description
 * @param <T>
 *
 */
@Slf4j
public class StreamImportListener<T> implements ReadListener<T> {

    private List<T> dataList = new ArrayList();
    private final List<ErrorMessage> errorMessageList = new ArrayList();

    private ImportListenerCallback<T> callback;

    public StreamImportListener(ImportListenerCallback<T> callback) {
        this.callback = callback;
    }

    private Integer customBatchCount;
    private Long hasProcessedNum;
    private Long successedNum;

    private ImportProcessor processor;

    private static final Integer BATCH_COUNT = 1000;

    public void init(Integer customBatchCount, ImportProcessor importProcessor) {
        hasProcessedNum = 0L;
        successedNum = 0L;
        processor = importProcessor;
        if (customBatchCount == null) {
            this.customBatchCount = BATCH_COUNT;
        } else {
            if (customBatchCount > BATCH_COUNT) {
                this.customBatchCount = BATCH_COUNT;
            } else {
                this.customBatchCount = customBatchCount;
            }
        }
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.error("解析文件异常", exception);

    }

    @Override
    public void invoke(T data, AnalysisContext context) {
        log.debug("开始读取第{}行的数据", context.readRowHolder().getRowIndex() + 1);
        Set<ConstraintViolation<Object>> violations = Validators.validate(data);
        if (!violations.isEmpty()) {
            Set<String> messageSet =
                (Set)violations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet());
            this.errorMessageList.add(new ErrorMessage((long)(context.readRowHolder().getRowIndex() + 1), messageSet));
        } else {
            this.dataList.add(data);
        }
        if (this.dataList.size() >= customBatchCount) {
            this.callback.callback(this.dataList, this.errorMessageList);
            successedNum += this.dataList.size();
            hasProcessedNum += this.dataList.size() + this.errorMessageList.size();
            log.debug("数据批量处理完成，本次成功{}条，异常{}条，共处理{}条", dataList.size(), errorMessageList.size(), hasProcessedNum);
            this.dataList.clear();
            this.errorMessageList.clear();
            // 更新进度
            // processor.refresh(successedNum, hasProcessedNum);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if (!this.dataList.isEmpty()) {
            this.callback.callback(this.dataList, this.errorMessageList);
            hasProcessedNum += this.dataList.size() + this.errorMessageList.size();
            successedNum += this.dataList.size();
            log.debug("数据批量处理完成，本次成功{}条，异常{}条，共处理{}条", dataList.size(), errorMessageList.size(), hasProcessedNum);
            this.dataList.clear();
            this.errorMessageList.clear();
            // 更新进度
            // processor.refresh(successedNum, hasProcessedNum);

        }
    }
}
